//
// ManualKerning
// =============
// A Cinema 4D effector plugin to influence kerning of MoText objects
// By Andreas Block, January 19th 2012
// Mail: open@andreasblock.de
//
// Objectives of this project:
//
// Please send any bug reports to e-mail adress above.
//
// Feel free to use the ManualKerning plugin and its source to your liking.
// No responsibilities taken for whatsoever, though.
// If your C4D crashes in combination with this plugin, rather
// send the bugreport together with a description of your parameter
// settings to me (mail adress above) than to Maxon. It's more likely
// my fault than theirs.
// If you modify the source or have any suggestions or feature requests,
// I'd be glad to know about and integrate them.
// And finally: Although you're free to use this plugin where ever you
// like, I'd gladly receive a copy or an example of your work (it won't
// be redistributed without permission). If you're using this plugin in
// a commercial environment and make any profit of it, I kindly ask you
// to donate an amount of your choice (what ever you feel it's worth).
//
// Plugin Info:
// ------------
// Tested on: Cinema 4D R12 (Windows, x86)
//            Cinema 4D R13 (Windows, x86)
// TODO Win x64 + Mac still to come
//
// Version history:
// ----------------
// 00.00.01 | 2012-01-XX | First public release
//
// ToDos / Known bugs:
// - (Feature) Versioning
// - (Job, sticky) Refactor+Cleanup
// - (Job, sticky) Minor TODOs all over the code
// - (Job) MAC version
// - (Test) MAC version
// - (Job) GetParameter/SetParameter
// - (Issue) After scene load, rotation and scaling works incorrectly (C4D bug, workaround change MoText line height once)
// - (Feature) Font search/matching could be optimized (speedwise and precision wise)
// - (Feature) If there were a way to determine the slot we are used in (better checking of wrong usage)
// - (Feature) Autokerning could be taken a lot further
// - (Feature) Would be nice to have button to open all charater subgroups (...but how?)
//
// Coding style conventions:
// -------------------------
//   Indentation: 2 spaces, NO TABS, NEVER EVER!
//   Comments as C++ single line (with the exception of some macros)
//   Variables:
//   - Variablenames in camel case
//   - Variablenames start lower case letter
//   - Prefixes (combinations allowed):
//     - "g_" for class global variables
//     - "i" for integer (includes Bool and LONG) variables
//     - "p" for pointer or arrays
//     - "idx" for loop counter
//   Constants:
//   - Constantnames all upper case and seperated by "_"
//   - Prefixes:
//     - "ARR_" for arrays
//   - These rules may be overriden by rules for variable for
//     local variables declared constant
//   Functions:
//   - Functionnames in camel case
//   - Functionnames start upper case
//   Macros:
//   - Macronames all upper case and seperated by "_"
//   Jump labels:
//   - Jumplabels all upper case and seperated by "_"
//   - Prefixes:
//     - Upper letters of functionname it's located,
//       not seperated (mandatory!)
//
//------------------------------------------------------------------------
// File: manualkerning.h  - class header
//

//========================================================================
// If you modify and recompile this plugin, MAKE SURE YOU GET A NEW
// UNIQUE PLUGIN ID from Plugin Cafe - if you don't your new plugin
// WILL conflict with this one if both are loaded simultaneously!!!!!
//========================================================================
#ifndef _MANUALKERNING_H_
#define _MANUALKERNING_H_

#include "c4d.h"
#include "c4d_baseeffectorplugin.h"

#include "manualkerning_defines.h"
#include "manualkerning_types.h"

#ifdef USE_FREETYPE
#define USE_FREETYPE2_STATIC
#include "ft2build.h"
#include FT_FREETYPE_H
#endif

struct ManualKerningData
{
  Real     fBaseUnit;
  LONG     iNumChars;
  Bool     iFlagAutoKerning;
#ifdef USE_FREETYPE
  FT_Face  ftFace;
#endif
  String   sText;
  String   sTextDescr;
  Matrix   matGenMg;
  String   sNameCombined;
  String   sFontFile;

  Bool     iFlagLinebreak;
  Bool     iFlagOverride;
  LONG     iNumRules;
  Real     fAutoKerning;
  Bool     iFlagOffsetIncremental;
  Bool     iFlagSizeIncremental;
  Bool     iFlagRotationIncremental;
};

class ManualKerning : public EffectorData
{
  INSTANCEOF(ManualKerning, EffectorData)

public:
#ifdef USE_FREETYPE
    static FT_Library       g_library;
#endif
    ManualKerningData       g_ed;

    virtual Bool  ModifyDDescription(GeListNode *node, Description *description, AtomArray *ar);
    virtual Bool  GetDEnabling(GeListNode *node, const DescID &id, const GeData &t_data, DESCFLAGS_ENABLE flags, const BaseContainer *itemdesc);
    virtual Bool  Message(GeListNode *node, LONG type, void *t_data);
    virtual void  GetDimension(BaseObject *op, Vector *mp, Vector *rad);
    virtual LONG  GetEffectorFlags(void);

    virtual Bool  InitEffector(GeListNode *node);
    virtual void  FreeEffector(GeListNode *node);

    virtual void  InitPoints(BaseObject *op, BaseObject *gen, BaseDocument *doc, EffectorDataStruct *data, MoData *md, BaseThread *thread);
    virtual void  ModifyPoints(BaseObject *op, BaseObject *gen, BaseDocument *doc, EffectorDataStruct *data, MoData *md, BaseThread *thread);

    static NodeData* Alloc(void) { return gNew ManualKerning; }

private:
#ifdef USE_FREETYPE
    static char        g_pFontpath[MANUALKERNING_MAX_PATH_LEN];

    Bool FontFaceOpen(const Filename &fnFontFile);
#if (API_VERSION >= 13000)
    static LONG        g_iNumFonts;
    static tFontTable  g_arrFontTable[MANUALKERNING_MAX_FONTS];

    void FontTableInitR13(void);
    LONG FontTableFindCombinedR13(const String &sNameCombinedC4D);
    void FontAutoSetFilenameR13(BaseContainer * const bcData, const BaseContainer * const bcDataMoText, String &sStatus);
#endif (API_VERSION >= 13000)
#endif USE_FREETYPE
};

#endif _MANUALKERNING_H_
